package com.ice.day726.cas;

import lombok.extern.slf4j.Slf4j;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * @Author ice2020x
 * @Date 2022-08-15 15:31
 * @Description: 测试cas操作
 */
@Slf4j
public class Demo {

    volatile static int count = 0;

    /*
    用synchronized 耗时太长了，虽然可以保证结果的一致性
     */
    public static void request() throws InterruptedException {

        TimeUnit.MILLISECONDS.sleep(5);
            /*
            实际上count++是分为三个操作
            1、得到count的值记做A
            2、将A+1记作B B=A+1
            3、将B的值赋值给count
            可以用原子操作类解决这个问题
             */
//        count++;
        int expectCount ;
        while (!compareAndSwap((expectCount=getCount()),expectCount+1));
//        AtomicInteger

    }

    public static int getCount() {
        return count;
    }

    public static synchronized boolean compareAndSwap(int expectCount, int newCount) {
        // 判断当前值是否和期望值是否一致
        if (getCount() == expectCount) {
            count = newCount;
            return true;
        }
        return false;
    }

    public static void main(String[] args) {
        long startTime = System.currentTimeMillis();
        CountDownLatch countDownLatch = new CountDownLatch(100);
        for (int i = 0; i < 100; i++) {
            Thread thread = new Thread(() -> {
                try {
                    for (int j = 0; j < 10; j++) {
                        request();
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } finally {
                    countDownLatch.countDown();
                }
            });
            thread.start();
        }
        try {
            countDownLatch.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        long endTime = System.currentTimeMillis();
        log.debug("结果是：" + count);
        log.debug("耗时是" + (endTime - startTime));
    }
}
